package simulatepushpull;

import java.util.Arrays;
import java.util.Random;

/**
 *
 * @author Owen
 */
public class SimulatePull {
    private double inRate,nextIn,t,totalIn,CT,throughput;
    private double[] times,nextOut,arrayIn, arrayOut;
    private Queue[] queue = new Queue[4];
    private int wip, totalOuts, orders;
    private static int wip_max;
    //declaratie van de generators
    private Random RNG;
    private Gamma Gamma;
   

    public SimulatePull(Random RNG, double inR, int piw_max, int orders) {
        inRate = inR;
        arrayIn = new double[orders];
        arrayOut = new double[orders];
        wip = 0;
        this.orders = orders;
        wip_max = piw_max;  
        this.RNG = RNG;
        Gamma = new Gamma(RNG);
        //instantiëren van de generators

        t = 0;
        nextOut= new double[3];
        nextIn = getNextIn();
        System.out.println(nextIn + " " + wip_max);
        
        for (int i = 0; i < nextOut.length; i++) {
            nextOut[i] = Long.MAX_VALUE;
        }
        for (int i = 0; i < queue.length; i++) {
            queue[i] = new Queue();
        }
        times = new double[]{nextIn, nextOut[0], nextOut[1], nextOut[2]};
        Arrays.sort(times);
    }
     public double getNextIn() {
        
        nextIn = t + Math.log(1-RNG.nextDouble())*(-12); 
        totalIn++;
        System.out.println("totalIn = " + totalIn);
        return nextIn;
    }    
    public double getNextOut(int id) {
        if (id == 0) {
            nextOut[id] = t + RNG.nextGaussian()*1.8+9;
        }
        if (id == 1) {

            nextOut[id] = t + Math.log(1-RNG.nextDouble())/-0.1;

        }
        if (id == 2) {
            nextOut[id] = t + Gamma.sampleGamma(4,2.4);
        }
        
        return nextOut[id];
    }     
    public double getCT()
    {
        for (int i = 0 ; i < arrayIn.length; i++)
        {
            CT += arrayOut[i] - arrayIn[i];
            
        }
        CT = CT / arrayIn.length;
        return CT;
        
        
    }
    
    public double getTroughput()
    {
    throughput = arrayIn.length/(arrayOut[arrayIn.length -1] - arrayIn[0]);
        return throughput;
        
    }
     

    public int getServed(){
        System.out.println(queue[2].getServed());
        return queue[2].getServed();
    }
    public void processNextEvent() {
        times[0] = nextIn;
        System.out.println("Wip:" + wip);
        System.out.println("nextIn: " + nextIn);
        for (int i = 1; i < times.length; i++) 
        {
            times[i] = nextOut[i-1];
            int count = i - 1;
            System.out.println("nextOut[" + count + "]: " + nextOut[i-1]);
        }
        if (queue[3].queued > 0)
            System.out.println("WACHTRIJ: " + queue[3].queued);
        Arrays.sort(times);
                if(times[0] == nextIn && totalIn > orders)
        {
            for(int i = 0; i < times.length - 1; i++)
                  times[i] = times[i+1];
        }
        if (nextIn == times[0]) {
            System.out.println("EERSTE METHODE");
            t = nextIn;
            if (wip < wip_max){
            queue[0].in();
            wip ++;
            getNextIn();
            if (nextOut[0] == Long.MAX_VALUE)
                getNextOut(0);
            }
            else {
                queue[3].in();
                getNextIn();                
            }
            
        }
        if (nextOut[0] == times[0]) {
            t = nextOut[0];
            queue[0].out();
            queue[1].in();
            if (queue[0].getQueued() == 0)
                nextOut[0] = Long.MAX_VALUE;
            else
                getNextOut(0);
            if (nextOut[1] == Long.MAX_VALUE)
                getNextOut(1);
        }
        if (nextOut[1] == times[0]) {
            t = nextOut[1];
            queue[1].out();
            queue[2].in();
            if (queue[1].getQueued() == 0)
                nextOut[1] = Long.MAX_VALUE;
            else
                getNextOut(1);
            if (nextOut[2] == Long.MAX_VALUE)
                getNextOut(2);
        }
        if (nextOut[2] == times[0]) {
            t = nextOut[2];
            totalOuts++;
            arrayOut[totalOuts - 1] = nextOut[2];
            queue[2].out();
            wip --;
            if (queue[2].getQueued() == 0)
                nextOut[2] = Long.MAX_VALUE;
            else
                getNextOut(2); 
            
            if (queue[3].queued > 0){
                queue[3].out();
                if (queue[0].queued == 0)
                    getNextOut(0);
                queue[0].in();
                wip ++;
            }                
        }
        
    }
}
